from flask import Blueprint, session, jsonify
from flask_restful import Api, Resource, marshal, reqparse, fields
from ext import db
from datetime import datetime

from ext.encrypt import hash_md5
from ext.arg_check import CheckUserArgs, CheckBookArgs
from ext.reusability import base_result
from ext.marshal_field import user_info_marshal_with, book_simple_info_marshal_with

# 使用的模型
from apps.models.user import User, UserBookshelf
from apps.models.book import Book

# 创建蓝图
user_bp = Blueprint("user", __name__, url_prefix='/api/user')
api = Api(user_bp)


# 登录
class Login(Resource):

    login_parser = reqparse.RequestParser()
    login_parser.add_argument('email', type=str, location='form')
    login_parser.add_argument('password', type=str, location='form')

    def post(self):
        args = self.login_parser.parse_args()
        email = args.email
        password = args.password
    
        user = None
        result = base_result.copy()

        result['errors'] = CheckUserArgs(email=email,
                                         password=password,
                                         login_user=True,
                                         return_user=True).run()
        result['msg'] = '登陆失败'


        if type(result['errors']) == dict:
            return jsonify(result)
        else:
            user = result['errors']
            result['errors'] = {}
            result['success'] = 1
            result['msg'] = '登陆成功'
            result['data'] = marshal(user, user_info_marshal_with)
            session['islogin'] = user.id
            return jsonify(result)


api.add_resource(Login, '/login', endpoint='login')

# 获取登陆状态
class GetLoginStatus(Resource):

    def get(self):
        result = base_result.copy()
        result['success'] = 1
        result['msg'] = '获取登陆状态成功'
        return jsonify(result)
    

api.add_resource(GetLoginStatus, '/get_login_status', endpoint='get_login_status')


# 退出登录
class Logout(Resource):

    def get(self):
        session.clear()

        result = base_result.copy()
        result['success'] = 1
        result['msg'] = '已成功退出登录'

        return jsonify(result)


api.add_resource(Logout, '/logout', endpoint='logout')


# 注册
class Register(Resource):

    register_parser = reqparse.RequestParser()
    register_parser.add_argument('email', type=str, location='form')
    register_parser.add_argument('password', type=str, location='form')
    register_parser.add_argument('repassword', type=str, location='form')
    register_parser.add_argument('user_name', type=str, location='form')

    def post(self):
        args = self.register_parser.parse_args()
        email = args.email
        password = args.password
        repassword = args.repassword
        user_name = args.user_name

        result = base_result.copy()

        result['errors'] = CheckUserArgs(email=email,
                                         password=password,
                                         repassword=repassword,
                                         user_name=user_name,
                                         user_name_not_used=True,
                                         email_not_used=True).run()
        result['msg'] = '注册失败'

        if result["errors"] != {}:
            return jsonify(result)

        user = User()
        user.email = email
        user.password = hash_md5(password)
        user.user_name = user_name

        db.session.add(user)
        db.session.commit()

        session['islogin'] = user.id

        result['success'] = 1
        result['msg'] = '注册成功'
        result['data'] = marshal(user, user_info_marshal_with)
        return jsonify(result)


api.add_resource(Register, '/register', endpoint='register')


# 找回密码
class RetrievePassword(Resource):
    retrieve_password_parser = reqparse.RequestParser()
    retrieve_password_parser.add_argument('email',
                                          type=str,
                                          location=['args', 'form'])
    retrieve_password_parser.add_argument('captcha', type=str, location='args')
    retrieve_password_parser.add_argument('password',
                                          type=str,
                                          location='form')
    retrieve_password_parser.add_argument('repassword',
                                          type=str,
                                          location='form')

    # 验证邮箱
    def get(self):
        args = self.retrieve_password_parser.parse_args()
        email = args.email
        captcha = args.captcha

        result = base_result.copy()

        result['errors'] = CheckUserArgs(email=email, captcha=captcha).run()
        result['msg'] = '验证邮箱失败'

        if result['errors'] != {}:
            return jsonify(result)

        result['success'] = 1
        result['msg'] = '验证邮箱成功'
        result['data'] = {'email': email}
        return jsonify(result)

    # 设置新密码
    def post(self):
        args = self.retrieve_password_parser.parse_args()
        email = args.email
        password = args.password
        repassword = args.repassword

        result = base_result.copy()

        result['errors'] = CheckUserArgs(email=email,
                                         password=password,
                                         repassword=repassword,
                                         email_used=True).run()
        result['msg'] = '设置新密码失败'

        if result['errors'] != {}:
            return jsonify(result)

        user = User.query.filter(User.email == email).filter(
            User.is_del == False).first()
        user.password = hash_md5(password)

        db.session.add(user)
        db.session.commit()

        result['success'] = 1
        result['msg'] = '设置新密码成功'

        return jsonify(result)


api.add_resource(RetrievePassword,
                 '/retrieve_password',
                 endpoint='retrieve_password')


# 注销账号
class DelAccount(Resource):

    def get(self):
        id = session.get('islogin')

        user = User.query.get(id)
        user.is_del = True
        user.del_time = datetime.now()

        db.session.add(user)
        db.session.commit()

        session.clear()

        result = base_result.copy()
        result['success'] = 1
        result['msg'] = '已成功注销'

        return jsonify(result)


api.add_resource(DelAccount, '/del_account', endpoint='del_account')


# 获取本账号资料
class GetMyAccount(Resource):

    def get(self):
        id = session.get('islogin')

        user = User.query.get(id)

        result = base_result.copy()
        result['success'] = 1
        result['data'] = marshal(user, user_info_marshal_with)

        return jsonify(result)


api.add_resource(GetMyAccount, '/get_my_account', endpoint='get_my_account')


# 修改用户名
class ChangeUserName(Resource):
    change_user_name_parser = reqparse.RequestParser()
    change_user_name_parser.add_argument('user_name',
                                         type=str,
                                         location='form')

    def post(self):
        id = session.get('islogin')

        args = self.change_user_name_parser.parse_args()
        user_name = args.user_name

        result = base_result.copy()

        result['errors'] = CheckUserArgs(user_name=user_name,
                                         user_name_not_used=True).run()
        result['msg'] = '修改用户名失败'
        if result['errors'] != {}:
            return jsonify(result)

        user = User.query.get(id)
        user.user_name = user_name

        db.session.add(user)
        db.session.commit()

        result['success'] = 1
        result['msg'] = '修改用户名成功'

        return jsonify(result)


api.add_resource(ChangeUserName,
                 '/change_user_name',
                 endpoint='change_user_name')


# 修改密码
class ChangePassword(Resource):
    change_password_parser = reqparse.RequestParser()
    change_password_parser.add_argument('password', type=str, location='form')
    change_password_parser.add_argument('new_password',
                                        type=str,
                                        location='form')
    change_password_parser.add_argument('repassword',
                                        type=str,
                                        location='form')

    def post(self):
        id = session.get('islogin')

        args = self.change_password_parser.parse_args()
        password = args.password
        new_password = args.new_password
        repassword = args.repassword

        result = base_result.copy()

        # 内容检查
        result['errors'] = CheckUserArgs(password=password,
                                         repassword=repassword,
                                         new_password=new_password,
                                         user_id=id,
                                         password_right=True).run()
        result['msg'] = '修改密码失败'
        if result['errors'] != {}:
            return jsonify(result)

        user = User.query.get(id)
        user.password = hash_md5(new_password)

        db.session.add(user)
        db.session.commit()

        result['success'] = 1
        result['msg'] = '修改密码成功'

        return jsonify(result)


api.add_resource(ChangePassword,
                 '/change_password',
                 endpoint='change_password')


# 修改邮箱
class ChangeEmail(Resource):
    change_email_parser = reqparse.RequestParser()
    change_email_parser.add_argument('email', type=str, location='form')

    def post(self):
        id = session.get('islogin')

        args = self.change_email_parser.parse_args()
        email = args.email

        result = base_result.copy()

        result['errors'] = CheckUserArgs(email=email,
                                         email_not_used=True).run()
        result['msg'] = '修改邮箱失败'

        if result['errors'] != {}:
            return jsonify(result)

        user = User.query.get(id)
        user.email = email

        db.session.add(user)
        db.session.commit()

        result['success'] = 1
        result['msg'] = '修改邮箱成功'

        return jsonify(result)


api.add_resource(ChangeEmail, '/change_email', endpoint='change_email')


# 获取用户的书架
class GetBookshelf(Resource):
    get_bookshelf_parser = reqparse.RequestParser()
    get_bookshelf_parser.add_argument('page',
                                      type=int,
                                      location='args',
                                      default=1)
    get_bookshelf_parser.add_argument('per_page',
                                      type=int,
                                      location='args',
                                      default=10)
    get_bookshelf_parser.add_argument('book_id', type=int, location='args')

    # 获取书架
    def get(self):
        id = session.get('islogin')

        args = self.get_bookshelf_parser.parse_args()
        page = args.page
        per_page = args.per_page

        result = base_result.copy()

        bookshelf = UserBookshelf.query.filter(
            UserBookshelf.user_id == id).filter(
                UserBookshelf.is_del == False).paginate(page, per_page, False)

        book_list = []
        for book in bookshelf.items:
            book_info = Book.query.get(book.book_id)
            book_list.append(marshal(book_info, book_simple_info_marshal_with))

        result['success'] = 1
        result['msg'] = '获取书架成功'
        result['data'] = {
            'has_next': bookshelf.has_next,
            'page': bookshelf.page,
            'per_page': bookshelf.per_page,
            'total': bookshelf.total,
            'pages': bookshelf.pages,
            'items': book_list
        }

        return jsonify(result)


api.add_resource(GetBookshelf, '/get_bookshelf', endpoint='get_bookshelf')


# 加入书架
class AddBookshelf(Resource):
    add_bookshelf_parser = reqparse.RequestParser()
    add_bookshelf_parser.add_argument('book_id', type=int, location='args')

    def get(self):
        id = session.get('islogin')

        args = self.add_bookshelf_parser.parse_args()
        book_id = args.book_id

        result = base_result.copy()

        result['errors'] = CheckBookArgs(book_id=book_id).run()
        if result['errors'] != {}:
            result['msg'] = '加入书架失败'
            return jsonify(result)

        bookshelf = UserBookshelf.query.filter(
            UserBookshelf.user_id == id).filter(
                UserBookshelf.book_id == book_id).filter(
                    UserBookshelf.is_del == False).first()

        if not bookshelf:
            bookshelf = UserBookshelf()
            bookshelf.user_id = id
            bookshelf.book_id = book_id

            db.session.add(bookshelf)
            db.session.commit()

        result['success'] = 1
        result['msg'] = '加入书架成功'

        return jsonify(result)


api.add_resource(AddBookshelf, '/add_bookshelf', endpoint='add_bookshelf')


# 移出书架
class RemoveBookshelf(Resource):
    remove_bookshelf_parser = reqparse.RequestParser()
    remove_bookshelf_parser.add_argument('book_id', type=int, location='args')

    def get(self):
        id = session.get('islogin')

        args = self.remove_bookshelf_parser.parse_args()
        book_id = args.book_id

        result = base_result.copy()

        bookshelf = UserBookshelf.query.filter(
            UserBookshelf.user_id == id).filter(
                UserBookshelf.book_id == book_id).filter(
                    UserBookshelf.is_del == False).first()
        if bookshelf:
            bookshelf.is_del = True
            bookshelf.del_time = datetime.now()

            db.session.add(bookshelf)
            db.session.commit()

        result['success'] = 1
        result['msg'] = '移出书架成功'

        return jsonify(result)


api.add_resource(RemoveBookshelf,
                 '/remove_bookshelf',
                 endpoint='remove_bookshelf')


# 查询是否加入到书架
class IsInBookshelf(Resource):
    is_in_bookshelf_parser = reqparse.RequestParser()
    is_in_bookshelf_parser.add_argument('book_id', type=int, location='args')

    def get(self):
        id = session.get('islogin')

        args = self.is_in_bookshelf_parser.parse_args()
        book_id = args.book_id

        result = base_result.copy()

        bookshelf = UserBookshelf.query.filter(
            UserBookshelf.user_id == id).filter(
                UserBookshelf.book_id == book_id).first()
        if bookshelf:
            result['success'] = 1
            result['msg'] = '已加入书架'
        else:
            result['success'] = 0
            result['msg'] = '未加入书架'

        return jsonify(result)


api.add_resource(IsInBookshelf, '/is_in_bookshelf', endpoint='is_in_bookshelf')
